# @Time    : 2022/10/13 21:02
# @Author  : 南黎
# @FileName: 4.分析不同的初始簇中心带来的影响.py
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib
from  sklearn.cluster import KMeans
#读取数据
DFdata=pd.read_csv("testSet.csv")
data=DFdata.values#dataframe数据类型转为列表
# print(data)
#设置 matplotlib rc配置文件
matplotlib.rcParams['font.sans-serif'] = [u'SimHei'] # 用来设置字体样式以正常显示中文标签
matplotlib.rcParams['axes.unicode_minus'] = False # 设置为 Fasle 来解决负号的乱码问题

k = 8  # 假设聚类为 8 类，默认分为 8 个 簇

def myTest(random_state):
    # 构建算法模型
    km = KMeans(n_clusters=k,init="random",random_state=random_state) # n_clusters参数表示分成几个簇（此处k=3）
    # - n_clusters：int，可选，默认值：8 要形成的簇数以及要生成的质心数。
    # - max_iter：整数，默认值：300 k - means 算法单次运行的最大迭代次数。
    # - n_init：整数，默认值：10使用不同质心种子运行 k - means算法的次数。就惯性而言，最终结果将是n_init连续运行的最佳输出。
    # - init: 设置为random结合random_state起到初始化中心的作用 {'k-means++', 'random' or an ndarray}初始化方法，默认为'k-means++' ：以智能方式为k - means聚类选择初始聚类中心以加速收敛。
    # - random_state：整数或 numpy.RandomState，可选用于初始化中心的生成器。如果给出一个整数，它会修复种子。默认为全局 numpy 随机数生成器。详细：int，默认 0

    km.fit(data)

    # 获取聚类后样本所属簇的对应编号（label_pred）
    label_pred = km.labels_  # labels_属性表示每个点的分簇号，会得到一个关于簇编号的数组
    centroids = km.cluster_centers_  #cluster_center 属性用来获取簇的质心点，得到一个关于质心的二维数组，形如[[x1,y1],[x2,y2],[x3,x3]]

    # 未聚类前的数据分布图
    plt.subplot(121)
    plt.scatter(data[:, 0], data[:, 1], s=50)
    plt.xlabel('x')
    plt.ylabel('y')
    plt.title("未聚类之前")
    # wspace 两个子图之间保留的空间宽度
    plt.subplots_adjust(wspace=0.5) # subplots_adjust（）用于调整边距和子图间距
    # 聚类后的分布图
    plt.subplot(122)
    # c：表示颜色和色彩序列，此处与 cmap 颜色映射一起使用（cool是颜色映射值）s表示散点的的大小，marker表示标记样式（散点样式）
    plt.scatter(data[:, 0], data[:, 1], c=label_pred, s=50, cmap='cool')
    # 绘制质心点
    plt.scatter(centroids[:,0],centroids[:,1],c='red',marker='o',s=100)
    plt.xlabel('x')
    plt.ylabel('y')
    plt.title("random_state={}  结果".format(random_state))
    plt.savefig("4/4.分析不同的初始簇中心带来的影响random_state={}.png".format(random_state))
    plt.show()
for random_state in range(1000,6000,1000):
    myTest(random_state)